#include "Predictor.h"
#include "GobangDoc.h"
#include "score.h"
#include "Judge.h"

Predictor::Predictor(CGobangDoc* doc,BoardState predictState)
	:pDoc(doc),judge(doc),x(0),y(0),myState(predictState){
	}

CPoint Predictor::getPrediction(int depth){
	predict(depth,-GB_INFINITY,GB_INFINITY);
	return CPoint(x,y);
}

int Predictor::predict(int depth,int alpha,int beta){
	int lastX=pDoc->GetLastMove().x;
	int lastY=pDoc->GetLastMove().y;

	if(pDoc->CheckResult(lastX,lastY)==BLACK_WIN || pDoc->CheckResult(lastX,lastY)==WHITE_WIN){
		GameResult rst=pDoc->CheckResult(lastX,lastY);

		if((rst==BLACK_WIN && myState==BLACK) || (rst==WHITE_WIN && myState==WHITE)){
			return GB_1;
		}
		if((rst==BLACK_WIN && myState==WHITE) || (rst==WHITE_WIN && myState==BLACK)){
			return -GB_1;
		}
	}
	if(depth==0){
		int whiteScore=0;
		int blackScore=0;

		for(int i=-2;i<=2;++i){
			for(int j=-2;j<=2;++j){
				if(pDoc->CheckBoarder(lastX+i,lastY+j)){
					whiteScore+=judge.evaluate(lastX+i,lastY+j,WHITE);
					blackScore+=judge.evaluate(lastX+i,lastY+j,BLACK);
				}
			}
		}

		if(myState==BLACK){
			return blackScore-whiteScore;
		}
		else{
			return whiteScore-blackScore;
		}
	}
	else{
		if((pDoc->IsBlackChess() && myState==BLACK) || (!pDoc->IsBlackChess() && myState==WHITE)){
			int score=0;

			for(int i=-2;i<=2;++i){
				for(int j=-2;j<=2;++j){
					if(pDoc->CheckAvailable(lastX+i,lastY+j)){
						pDoc->SetBoardState(lastX+i,lastY+j);
						score=predict(depth-1,alpha,beta);
						pDoc->UndoChess();

						if(score>=beta){
							x=lastX+i;
							y=lastY+j;
							return score;
						}
						if(score>alpha){
							alpha=score;
							x=lastX+i;
							y=lastY+j;
						}
					}
				}
			}

			return alpha;
		}

		if((pDoc->IsBlackChess() && myState==WHITE) || (!pDoc->IsBlackChess() && myState==BLACK)){
			int score=0;

			for(int i=-2;i<=2;++i){
				for(int j=-2;j<=2;++j){
					if(pDoc->CheckAvailable(lastX+i,lastY+j)){
						pDoc->SetBoardState(lastX+i,lastY+j);
						score=predict(depth-1,alpha,beta);
						pDoc->UndoChess();

						if(score<=alpha){
							x=lastX+i;
							y=lastY+j;
							return score;
						}
						if(score<beta){
							x=lastX+i;
							y=lastY+j;
							beta=score;
						}
					}
				}
			}

			return beta;
		}
	}
}
